import json
import pandas
import requests
from vfeeds import DataFeed
from websockets.sync.client import connect


class TqsdkFeed(DataFeed):
    tqSec = 1000000000
    intervalMaps = {
        "1min": 1, "5min": 5, "15min": 15, "30min": 30, "H": 60,
        "D": 1440, "W": 1440, "M": 1440
    }

    def get_detail(self):
        results = list()
        respond = requests.get("https://openmd.shinnytech.com/t/md/symbols/latest.json").json()
        for item in respond.values():
            if not item["expired"] and item["class"] == "FUTURE":
                results.append({
                    "title": item["ins_name"],
                    "symbol": item["instrument_id"],
                    "exchange": item["exchange_id"],
                    "volume_multiple": item["volume_multiple"],
                    "price_tick": item["price_tick"],
                    "min_volume": item["open_min_limit_order_volume"],
                    "product_id": item["product_id"],
                    "margin": item["margin"],
                    "commission": item["commission"],
                    "trading_time": item["trading_time"]
                })
        results = pandas.DataFrame(results)
        return results

    @staticmethod
    def send_message(ws, message):
        ws.send(json.dumps(message))

    def peek_message(self, ws):
        self.send_message(ws, {"aid": "peek_message"})

    def get_history(self, symbol, interval, start, end, **kwargs):
        second = self.intervalMaps[interval] * 60 * self.tqSec
        with connect("wss://openmd.shinnytech.com/t/md/front/mobile") as ws:
            ws.recv()
            self.peek_message(ws)
            ws.recv()
            self.peek_message(ws)
            self.send_message(ws, {
                "aid": "set_chart", "chart_id": "PC_kline_chart", "ins_list": symbol, "duration": second,
                "view_width": 2000
            })
            ws.recv()
            self.peek_message(ws)
            respond = ws.recv()
            respond = json.loads(respond)
            respond = respond["data"][0]["klines"][symbol][str(second)]["data"]
            respond = pandas.DataFrame(respond.values())
            respond = respond[["datetime", "open", "high", "low", "close", "volume"]]
            respond["datetime"] = pandas.to_datetime(
                respond["datetime"] / self.tqSec, origin="1970-01-01 08:00:00", unit="s"
            )
            respond = respond.set_index(pandas.to_datetime(respond["datetime"]))
            respond = respond.resample(interval).agg({
                "datetime": "last", "open": "first", "high": "max", "low": "min",
                "close": "last", "volume": "sum"
            }).dropna()
            respond = respond.loc[respond.datetime.ge(start) & respond.datetime.le(end)]
            respond["datetime"] = respond["datetime"].dt.strftime('%Y-%m-%d %H:%M:%S')
            return respond.to_dict(orient="records")

    def get_ticker(self, symbol):
        with connect("wss://openmd.shinnytech.com/t/md/front/mobile") as ws:
            ws.recv()
            self.peek_message(ws)
            ws.recv()
            self.peek_message(ws)
            self.send_message(ws, {"aid": "subscribe_quote", "ins_list": symbol})
            resp = ws.recv()
            resp = json.loads(resp)
            resp = resp["data"][0]["quotes"][symbol]
            return {
                "datetime": resp["datetime"][:19],
                "open": resp["open"],
                "high": resp["highest"],
                "low": resp["lowest"],
                "close": resp["last_price"],
                "pre_close": resp["pre_close"],
                "volume": resp["volume"],
                "amount": resp["amount"],
            }


__all__ = [TqsdkFeed]